using System;
using System.Net;
using System.Net.Sockets;
using System.Collections;

namespace LANamp
{
    public class ServerList
	{
		private ArrayList servers;
		private int lives;
		public delegate void UpdateEvent();
        public delegate void ServerAddedEvent(Server server);
        public delegate void ServerGoneEvent(Server server);
        public event UpdateEvent Updated;
        public event ServerAddedEvent ServerAdded;
        public event ServerGoneEvent ServerGone;
	
		public ServerList(int Lives)
		{
			servers = new ArrayList();
			lives = Lives;
		}
		
		public ServerList(): this(5)
		{
		}
		
		public Server GetServer(string IPaddress)
		{
			Server gs = null;
            lock (servers)
            {
                foreach (Server server in servers)
                {
                    if (server.IPaddress == IPaddress) gs = server;
                    if (server.Name == IPaddress) gs = server;
                }
            }
			return gs;
		}

        public Server GetServer(int Index)
        {
            if (Index <= servers.Count)
            {
                return (Server)servers[Index];
            }
            else
            {
                return null;
            }
        }

        public Server GetServerByName(string Name)
        {
            Server gs = null;
            lock (servers)
            {
                foreach (Server server in servers)
                {
                    if (server.Name == Name) gs = server;
                }
            }
            return gs;
        }

		public Server GetServer(EndPoint ep)
		{
			return GetServer(Server.ToIP(ep));
		}

		public void Alive(String IPaddress, String Name, String Hostname, String AppVersion, String WinampVersion)
		{
			bool handled = false;
            bool needupdate = false;
            Server newServer = null;
            lock (servers)
            {
                foreach (Server server in servers)
                {
                    if (server.IPaddress == IPaddress)
                    {
                        handled = true;
                        server.Lives = Lives;
                        if (server.Name != Name)
                        {
                            server.Name = Name;
                            needupdate = true;
                        }
                        if (server.Hostname != Hostname)
                        {
                            server.Hostname = Hostname;
                            needupdate = true;
                        }
                        if (server.Version != AppVersion)
                        {
                            server.Version = AppVersion;
                            needupdate = true;
                        }
                        if (server.WinampVersion != WinampVersion)
                        {
                            server.WinampVersion = WinampVersion;
                            needupdate = true;
                        }
                    }
                }
            }
            if (!handled)
            {
                lock (servers)
                {
                    newServer = new Server(IPaddress, Name, Hostname, AppVersion, WinampVersion, Lives);
                    servers.Add(newServer);
                    needupdate = true;
                }
            }
            if ((needupdate) && (Updated != null)) Updated();
            if ((newServer != null) && (ServerAdded != null)) ServerAdded(newServer);
		}
		
		public void Alive(EndPoint ep, String Name, String Hostname, String AppVersion, string WinampVersion)
		{
			Alive(Server.ToIP(ep), Name, Hostname, AppVersion, WinampVersion);
		}
		
		public void Gone(String IPaddress)
		{
            Server goneServer = null;
            lock (servers)
            {
                foreach (Server server in servers)
                {
                    if (server.IPaddress == IPaddress)
                    {
                        goneServer = server;
                        break;
                    }
                }
            }
            if (goneServer != null) {
                lock(servers) {
                    servers.Remove(goneServer);
                }
                if (Updated != null) Updated();
                if (ServerGone != null) ServerGone(goneServer);
            }
        }

		public void Gone(EndPoint ep)
		{
			Gone(Server.ToIP(ep));
		}

		public ArrayList Items
		{
			get
			{
                lock (servers)
                {
                    return servers;
                }
			}
		}
		public int Count
		{
			get
			{
                lock (servers)
                {
                    return servers.Count;
                }
			}
		}

		public void TimeOut()
		{
            ArrayList updatedservers = new ArrayList();
            lock (servers)
            {
                for (int i = servers.Count; i > 0; i--)
                {
                    Server server = servers[i - 1] as Server;
                    server.Lives -= 1;
                    if (server.Lives <= 0)
                    {
                        Server goneServer = server;
                        servers.Remove(server);
                        updatedservers.Add(goneServer);
                    }
                }
            }
            if ((updatedservers.Count > 0) && (Updated != null)) Updated();
            if (ServerGone != null)
            {
                foreach (Server server in updatedservers)
                {
                    ServerGone(server);
                }
            }
            updatedservers.Clear();
        }
		
		public int Lives
		{
			get
			{
				return lives;
			}
			set
			{
				lives = value;
			}
		}
	}
}
